package gitee.autodeploy;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.SilentCssErrorHandler;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.*;
import com.gargoylesoftware.htmlunit.util.Cookie;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpStatus;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.ClientCookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BasicClientCookie;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.logging.Level;


/**
 * 自动部署Gitee pages
 *
 * @author zhangcheng
 */
public class GiteeDeployMain {

    private static final String PARAMS = "branch=%s&build_directory=%s&force_https=true";
    private static final int ERROR_CODE = 300;

    private static final Map<String, String> HEADER = new HashMap<>(16);

    private static final Log log = LogFactory.getLog(GiteeDeployMain.class);

    static {
        HEADER.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        HEADER.put("X-CSRF-Token", "");
        HEADER.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36");
        HEADER.put("X-Requested-With", "XMLHttpRequest");
        HEADER.put("Accept", "*/*");
        HEADER.put("Accept-Encoding", "gzip, deflate, br");
        HEADER.put("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7,und;q=0.6,de;q=0.5");
        HEADER.put("Connection", "keep-alive");
        HEADER.put("Host", "gitee.com");
        HEADER.put("Origin", "https://gitee.com");
        HEADER.put("Sec-Fetch-Dest", "empty");
        HEADER.put("Sec-Fetch-Mode", "cors");
        HEADER.put("Sec-Fetch-Site", "same-origin");
        java.util.logging.Logger.getLogger("com.gargoylesoftware.htmlunit").setLevel(Level.OFF);
        java.util.logging.Logger.getLogger("org.apache.http.client").setLevel(Level.OFF);
    }

    public static void main(String[] args) {
        log.info("开始自动部署Gitee Pages ...[忽略Gitee登陆警告邮件或微信等信息]");
        String giteeUserName = System.getProperty("giteeUserName");
        String giteePwd = System.getProperty("giteePwd");
        String giteeName = System.getProperty("giteeName");
        String repoName = System.getProperty("repoName");
        String branch = System.getProperty("branch");
        String path = System.getProperty("build_directory");

        if (null == branch) {
            branch = "master";
        }

        if (null == path) {
            path = "";
        }

        Set<Cookie> cookies;
        try (WebClient webClient = new WebClient(BrowserVersion.CHROME)) {
            // 配置webClient
            // ajax
            webClient.setAjaxController(new NicelyResynchronizingAjaxController());
            // 支持js
            webClient.getOptions().setJavaScriptEnabled(true);
            // 忽略js错误
            webClient.getOptions().setThrowExceptionOnScriptError(false);
            // 忽略css错误
            webClient.setCssErrorHandler(new SilentCssErrorHandler());
            // 不执行CSS渲染
            webClient.getOptions().setCssEnabled(false);
            // 超时时间
            webClient.getOptions().setTimeout(3000);
            // 允许重定向
            webClient.getOptions().setRedirectEnabled(true);
            // 允许cookie
            webClient.getCookieManager().setCookiesEnabled(true);
            log.info("准备使用[" + giteeUserName + "]账号登陆Gitee");
            // 开始请求网站
            HtmlPage loginPage = webClient.getPage("https://gitee.com/login");
            while (null == loginPage.getElementByName("user[login]")) {
                Thread.sleep(3000);
            }
            // 用户名input
            HtmlTextInput username = loginPage.getElementByName("user[login]");
            // 密码input
            HtmlPasswordInput password = loginPage.getElementByName("user[password]");
            // 设置input的value
            username.setValueAttribute(giteeUserName);
            password.setValueAttribute(giteePwd);
            // 登陆
            HtmlSubmitInput submitInput = loginPage.getElementByName("commit");
            HtmlPage home = submitInput.click();
            log.info("登陆成功，准备自动部署Pages...");
            cookies = webClient.getCookieManager().getCookies();
            List<DomElement> list = home.getElementsByName("csrf-token");

            List<BasicClientCookie> cookieList = new ArrayList<>();
            cookies.forEach(c -> {
                BasicClientCookie cookie = new BasicClientCookie(c.getName(), c.getValue());
                cookie.setDomain("gitee.com");
                cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "true");
                cookieList.add(cookie);
            });
            String token = list.get(0).getAttribute("content");
            HEADER.put("X-CSRF-Token", token);
            HEADER.put("Referer", getReferUrl(giteeName, repoName));
            HttpPost httpPost = new HttpPost(getPostUrl(giteeName, repoName));
            // 设置参数
            String params = String.format(PARAMS, branch, path);
            log.info("请求参数为:" + params);
            StringEntity stringEntity = new StringEntity(params, StandardCharsets.UTF_8);
            stringEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
            httpPost.setEntity(stringEntity);
            HEADER.forEach(httpPost::setHeader);
            int returnCode = sendHttpPost(httpPost, cookieList);
            // 判断响应状态
            if (returnCode >= ERROR_CODE) {
                log.warn("自动部署失败~");
            }
            if (HttpStatus.SC_OK == returnCode) {
                log.info("自动部署成功！！！");
            }
        } catch (Exception e) {
            log.error(e);
        }
    }

    private static String getPostUrl(String giteeName, String repoName) {
        return String.format("https://gitee.com/%s/%s/pages/rebuild", giteeName, repoName);
    }

    private static String getReferUrl(String giteeName, String repoName) {
        return String.format("https://gitee.com/%s/%s/pages", giteeName, repoName);
    }

    /**
     * 发送Post请求
     *
     * @param httpPost post
     * @param cookies  HtmlUnit爬来的cookie
     * @return status code
     */
    private static int sendHttpPost(HttpPost httpPost, List<BasicClientCookie> cookies) throws IOException {
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(50000).setConnectTimeout(50000)
                .setConnectionRequestTimeout(50000).build();
        CookieStore store = new BasicCookieStore();
        cookies.forEach(store::addCookie);
        CloseableHttpClient httpClient = HttpClients.custom()
                // 设置请求配置
                .setDefaultRequestConfig(requestConfig)
                // 设置重试次数
                .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
                .setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36")
                .setDefaultCookieStore(store)
                .build();
        // 配置请求信息
        httpPost.setConfig(requestConfig);
        // 执行请求
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            return response.getStatusLine().getStatusCode();
        }
    }
}
